using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using MbUnit.Framework;
using ShouldIt.Core;

namespace ShouldIt.MbUnit
{
    [Export(typeof(IAssertProvider))]
    public class AssertProvider : IAssertProvider
    {
        public void AreEqual(object expected, object actual)
        {
            Assert.AreEqual(expected, actual);
        }

        public void AreNotEqual(object expected, object actual)
        {
            Assert.AreNotEqual(expected, actual);
        }

        public void IsNotNull(object obj)
        {
            Assert.IsNotNull(obj);
        }

        public void IsNull(object value)
        {
            Assert.IsNull(value);
        }

        public void IsFalse(bool value)
        {
            Assert.IsFalse(value);   
        }

        public void IsTrue(bool value)
        {
            Assert.IsTrue(value);   
        }

        public void Fail(string messageFormat, params object[] args)
        {
            Assert.Fail(messageFormat, args);
        }

        public void Contains<T>(T item, IEnumerable<T> enumerable)
        {
            CollectionAssert.Contains(AsList(enumerable), item);
        }

        public void NotContains<T>(T item, IEnumerable<T> enumerable)
        {
            Assert.IsFalse(enumerable.Contains(item));
            //CollectionAssert.DoesNotContain(AsList(enumerable), item); this has a bug; throws unless you provide message with args
        }

        public void Greater(int left, int right)
        {
            Assert.GreaterThan(left, right);
        }

        public void GreaterOrEqual(int left, int right)
        {
            Assert.GreaterEqualThan(left, right);
        }

        public void AreSame(object expected, object actual)
        {
            Assert.AreSame(expected, actual);
        }

        public void AreNotSame(object unExpected, object actual)
        {
            Assert.AreNotSame(unExpected, actual);
        }

        public void IsSubstringOf(string actual, string expectedSubstring)
        {
            Assert.Contains(actual, expectedSubstring);
        }

        public void IsInstanceOfType(object actual, Type expectedType)
        {
            Assert.IsInstanceOfType(expectedType, actual);
        }

        public void IsNotInstanceOfType(object actual, Type expectedType)
        {
            Assert.IsNotInstanceOfType(expectedType, actual);
        }

        private static List<T> AsList<T>(IEnumerable<T> e)
        {
            return e is List<T>
                       ? (List<T>)e
                       : e.ToList();
        }
    }
}